# -*- coding:utf-8 -*-
"""
-------------------------------------------------
   File Name:      main.py
   Author:         luzhongfu
   date:           2020/05/15
-------------------------------------------------
"""

import os
import decimal

from openpyxl import Workbook

from handler.reader import ExcelReader
from handler.parser import MappingRuleParser
from utils import logs
from utils.do_cprofile import do_cprofile

try:
    import config  # type: ignore
except:
    import config_demo as config


def try_parse_field(parser: MappingRuleParser, field: str, source_row: int):
    try:
        value = parser.parse_field_value(field, source_row)
    except Exception as e:
        # print(f'{field} 第{source_row}行解析失败:{e}')
        return
    return value


def get_sum_title_ruls():
    sum_title_rule = {}
    for rule in config.统计规则:
        sum_fun = rule.get('sum_fun')
        if sum_fun == 'sum':
            if rule.get('type') != 'number':
                raise ValueError('仅支持对number类型进行求和运算')
            title = rule.get('title')
            if title is None:
                raise ValueError(f'{rule}缺少title配置')
            sum_title_rule[title] = rule
    return sum_title_rule


@do_cprofile('./main.prof')
def main():
    # 初始化
    try:
        level = config.日志等级  # type: ignore
    except:
        level = logs.INFO
    logs.LogConfig(level=level, is_stream=False)

    reader = ExcelReader()
    parser = MappingRuleParser(reader)

    reader.add_file(config.源文件)
    for path in config.翻译列表:
        reader.add_file(path)

    for trans in config.翻译项:
        parser.add_extra_value(trans, config.翻译项[trans])

    # 根据映射规则写入文件
    groups = {}  # {'group_name': {'sheet': sheet, 'write_row': 0}}
    for rules in config.映射规则:
        source_row = 1  # 忽略标题
        while True:
            source_row += 1

            group_name = try_parse_field(parser, config.分组列, source_row)
            if not group_name:
                break
            group = groups.get(group_name)
            # 新建sheet
            if group is None:
                wb = Workbook()
                sheet = wb.active
                column = 0
                # 写标题
                for rule in rules:
                    column += 1
                    title = rule.get('title')
                    if title is None:
                        raise ValueError(f'未设置标题(title) {rule}')
                    sheet.cell(row=1, column=column).value = title

                reader.add_mem_file(group_name, sheet)
                group = {'wb': wb, 'sheet': sheet, 'write_row': 2}
                groups[group_name] = group

            # 写入数据
            sheet = group['sheet']
            write_row = group['write_row']
            column = 0
            for rule in rules:
                column += 1

                _cell = sheet.cell(row=write_row, column=column)
                _cell.value = parser.parse(group_name, rule, source_row)
                # fix type
                d_format = rule.get('format')
                if d_format:
                    _cell.number_format = d_format

            group['write_row'] = write_row + 1

    #  进行数据汇总运算
    title_rules = get_sum_title_ruls()
    ## sum_groups: {'filename': sum_group_rules}
    ## sum_group_rules: {'sum_group_name': sum_group_rule}
    ## sum_group_rule: {'sum_titles': sum_titles, sum_row: 0, 'source_row': 0}
    ## sum_titles = {'title': value}
    sum_groups = {}
    source_row = 1

    while True:
        source_row += 1
        filename = try_parse_field(parser, config.分组列, source_row)
        if not filename:
            break
        group = groups[filename]

        sum_group_rules = sum_groups.get(filename)
        if sum_group_rules is None:
            sum_group_rules = {}
            sum_groups[filename] = sum_group_rules

        sum_group_name = try_parse_field(parser, config.统计分组, source_row)
        if not sum_group_name:
            break
        # print('sum_group_name = ', sum_group_name)

        sum_group_rule = sum_group_rules.get(sum_group_name)
        if sum_group_rule is None:
            sum_group_rule = {}
            sum_group_rules[sum_group_name] = sum_group_rule
            sum_group_rule['sum_titles'] = {}
            write_row = group['write_row']
            sum_group_rule['sum_row'] = write_row
            group['write_row'] = write_row + 1
            for title in title_rules:
                sum_group_rule['sum_titles'][title] = decimal.Decimal(0)
            sum_group_rule['source_row'] = source_row  # 记录一条即可, 不需要计算的特征应该都一样

        for sum_title in sum_group_rule['sum_titles']:
            sum_title_rule = title_rules[sum_title]
            title_value = parser.parse(filename, sum_title_rule, source_row)
            title_value = decimal.Decimal(title_value)
            sum_title_value = sum_group_rule['sum_titles'][sum_title]
            sum_group_rule['sum_titles'][
                sum_title] = title_value + sum_title_value

    # 写入汇总数据
    for filename in sum_groups:
        group = groups[filename]
        sheet = group['sheet']
        sum_group_rules = sum_groups[filename]
        for sum_group_name in sum_group_rules:
            sum_group_rule = sum_group_rules[sum_group_name]
            write_row = sum_group_rule['sum_row']
            source_row = sum_group_rule['source_row']
            column = 0
            for rule in config.统计规则:
                column += 1
                value = ''
                if rule.get('sum_fun'):
                    value = sum_group_rule['sum_titles'][rule['title']]
                else:
                    value = parser.parse(filename, rule, source_row)
                _cell = sheet.cell(row=write_row, column=column)
                _cell.value = value

                d_format = rule.get('format')
                if d_format:
                    _cell.number_format = d_format

    # 保存文件
    filepath = os.path.join(os.getcwd(), 'data')
    if not os.path.exists(filepath):
        os.mkdir(filepath)
    for group_name in groups:
        sheet = groups[group_name]['wb']
        filename = '{}.xlsx'.format(group_name)
        sheet.save(os.path.join(filepath, filename))


if __name__ == "__main__":
    try:
        main()
    except Exception as e:
        log = logs.LogHandler(__name__)
        log.error(f'main error: {e}')
